Skip to content

MENDELU/Convert full item metadata to hyperlinks#1246

Open
jr-rk wants to merge 10 commits intocustomer/mendelufrom
mendelu/convert-full-item-metadata-to-hyperlinks
Open

MENDELU/Convert full item metadata to hyperlinks#1246
jr-rk wants to merge 10 commits intocustomer/mendelufrom
mendelu/convert-full-item-metadata-to-hyperlinks

Conversation

@jr-rk
Copy link

@jr-rk jr-rk commented Mar 10, 2026

Problem description

  • "Urobit hyperlinky v full item view pre specificke metadata 2h"

Copilot review

  • Requested review from Copilot

@jr-rk jr-rk requested a review from Copilot March 10, 2026 15:36
@jr-rk jr-rk self-assigned this Mar 10, 2026
@jr-rk jr-rk linked an issue Mar 10, 2026 that may be closed by this pull request
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the full item view to render URL-like metadata values as clickable hyperlinks, improving usability when metadata contains resolvable links (e.g., handle URLs).

Changes:

  • Added an isUrl helper on FullItemPageComponent to detect http(s) URLs.
  • Updated the full item metadata table to render detected URLs as <a> links (new tab + noopener noreferrer).
  • Added unit tests covering URL detection and link rendering behavior in the metadata table.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/app/item-page/full/full-item-page.component.ts Introduces isUrl helper used by the template to decide link vs. plain text rendering.
src/app/item-page/full/full-item-page.component.html Renders metadata values as <a> when isUrl(...) returns true.
src/app/item-page/full/full-item-page.component.spec.ts Adds tests for isUrl and verifies URL values render as clickable links in the metadata table.

@jr-rk jr-rk requested a review from milanmajchrak March 10, 2026 15:43
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

<a [routerLink]="link.routerLink" [queryParams]="link.queryParams">{{mdValue.value}}</a>
}
} @else {
<span [innerHTML]="makeLinks(mdValue.value)"></span>
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[innerHTML]="makeLinks(mdValue.value)" changes escaping semantics compared to {{mdValue.value}}: any HTML present in metadata values will now be rendered (after Angular sanitization) instead of displayed as plain text. If metadata is not meant to support HTML markup, consider avoiding innerHTML here and rendering links via bindings (or escaping the non-URL parts before inserting <a> tags) so the rest of the value remains text.

Suggested change
<span [innerHTML]="makeLinks(mdValue.value)"></span>
<span>{{mdValue.value}}</span>

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +12
export function makeLinks(text: string): string {
const regex = /(?:https?|ftp):\/\/[^\s)]+|www\.[^\s)]+/g;
return text?.replace(regex, (url) => {
const href = url.startsWith('www.') ? `https://${url}` : url;
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${url}</a>`;
});
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makeLinks is typed as (text: string) => string, but it uses optional chaining and can return undefined (and callers/tests pass null/undefined). This makes the util’s contract misleading for other consumers. Update the signature to accept string | null | undefined and return string | undefined (or normalize to an empty string) so the type reflects actual behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +41
// --- Internal search configuration ---
const SEARCH_PATH = '/search';
const SEARCH_FILTER_SUFFIX = ',equals';

/** Maps metadata keys to their corresponding search filter parameter. */
const SEARCH_FIELD_FILTERS: Record<string, string> = {
'dc.subject': 'f.subject',
'dc.contributor.author': 'f.author',
};
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For internal search links, the filter value is built by manually appending the operator suffix (,equals). The repo already has addOperatorToFilterValue in shared/search/search.utils.ts, which centralizes operator handling and avoids duplicating the operator list/regex behavior. Consider using that helper here instead of SEARCH_FILTER_SUFFIX + string concatenation.

Copilot uses AI. Check for mistakes.
Comment on lines +372 to +416
it('should convert URLs embedded in text', () => {
const result = makeLinks('Visit https://example.com for details');
expect(result).toContain('<a href="https://example.com"');
expect(result).toContain('Visit');
expect(result).toContain('for details');
});

it('should handle DOI / handle redirect URLs', () => {
const result = makeLinks('https://hdl.handle.net/123456789/1');
expect(result).toContain('<a href="https://hdl.handle.net/123456789/1"');
expect(result).toContain('rel="noopener noreferrer"');
});

it('should handle DOI resolver URLs', () => {
const result = makeLinks('https://doi.org/10.1234/test');
expect(result).toContain('<a href="https://doi.org/10.1234/test"');
});

it('should not create links for javascript: URIs', () => {
const result = makeLinks('javascript:alert(1)');
expect(result).not.toContain('<a');
expect(result).toBe('javascript:alert(1)');
});

it('should not create links for data: URIs', () => {
const result = makeLinks('data:text/html,<script>alert(1)</script>');
expect(result).not.toContain('<a');
});

it('should handle multiple URLs in one string', () => {
const result = makeLinks('See https://a.com and https://b.com');
expect(result).toContain('<a href="https://a.com"');
expect(result).toContain('<a href="https://b.com"');
});

it('should handle URLs with query parameters', () => {
const result = makeLinks('https://example.com/search?q=test&page=1');
expect(result).toContain('<a href="https://example.com/search?q=test&page=1"');
});

it('should handle URLs with fragments', () => {
const result = makeLinks('https://example.com/page#section');
expect(result).toContain('<a href="https://example.com/page#section"');
});

Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new makeLinks/getMetadataLink unit tests are added to full-item-page.component.spec.ts, which significantly increases the size/scope of a component spec for logic that lives in shared/utils/make-links.ts. To keep tests cohesive (and reduce future maintenance when the component changes), consider moving these util-focused tests into a dedicated make-links.spec.ts and leaving only the DOM rendering assertions in this component spec.

Suggested change
it('should convert URLs embedded in text', () => {
const result = makeLinks('Visit https://example.com for details');
expect(result).toContain('<a href="https://example.com"');
expect(result).toContain('Visit');
expect(result).toContain('for details');
});
it('should handle DOI / handle redirect URLs', () => {
const result = makeLinks('https://hdl.handle.net/123456789/1');
expect(result).toContain('<a href="https://hdl.handle.net/123456789/1"');
expect(result).toContain('rel="noopener noreferrer"');
});
it('should handle DOI resolver URLs', () => {
const result = makeLinks('https://doi.org/10.1234/test');
expect(result).toContain('<a href="https://doi.org/10.1234/test"');
});
it('should not create links for javascript: URIs', () => {
const result = makeLinks('javascript:alert(1)');
expect(result).not.toContain('<a');
expect(result).toBe('javascript:alert(1)');
});
it('should not create links for data: URIs', () => {
const result = makeLinks('data:text/html,<script>alert(1)</script>');
expect(result).not.toContain('<a');
});
it('should handle multiple URLs in one string', () => {
const result = makeLinks('See https://a.com and https://b.com');
expect(result).toContain('<a href="https://a.com"');
expect(result).toContain('<a href="https://b.com"');
});
it('should handle URLs with query parameters', () => {
const result = makeLinks('https://example.com/search?q=test&page=1');
expect(result).toContain('<a href="https://example.com/search?q=test&page=1"');
});
it('should handle URLs with fragments', () => {
const result = makeLinks('https://example.com/page#section');
expect(result).toContain('<a href="https://example.com/page#section"');
});

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MENDELU/Convert full item metadata values to hyperlinks

3 participants